from database.task import TaskTable
from database.taskrecord import TaskRecordTable
from database.parkrecord import ParkRecordTable
from database.user import UserTable
from models.exception import ParkAdminErrorCode, ParkAdminException
from models.query import TaskQuery, ParkQuery
from models.task import DbTask, NewTaskModel, EditTaskModel, OperationTaskModel, TaskStatus
from models.user import User
from models.taskrecord import DbTaskRecord
import re
import requests

spider_host = 'http://127.0.0.1:3769'

def verify_car_number(car_numbers: str) -> bool:
    numbers = car_numbers.split("\n")
    for number in numbers:
        number = number.strip()
        pattern = r"^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]{1}[A-Z]{1}.{5,6}$"
        valid = re.match(pattern, number) is not None
        if not valid:
            raise ParkAdminException(ParkAdminErrorCode.InvalidCarNumber, number)
            
def buildDbTaskRecord(userid, taskid, content):
    dbtaskrecord = DbTaskRecord()
    dbtaskrecord.user_id = userid
    dbtaskrecord.task_id = taskid
    dbtaskrecord.content = content
    return dbtaskrecord

def findDbTaskRecord(taskid) -> DbTask:
    with TaskTable() as db:
        records = db.query(TaskQuery(id = taskid), False)
        if len(records) == 0:
            return None
        return records[0]

def new_task(model: NewTaskModel, user: User):
    verify_car_number(model.car_numbers)
    dbtask = DbTask()
    dbtask.name = model.name
    dbtask.user_id = user.id
    dbtask.platform_id = model.platform_id
    dbtask.proxy = model.proxy
    dbtask.threads = model.threads
    dbtask.car_numbers = model.car_numbers
    dbtask.status = TaskStatus.New
    with TaskTable() as db:
        id = db.insert(dbtask)
        db.commit()
        with TaskRecordTable() as dbrecord:
            dbrecord.insert(buildDbTaskRecord(user.id, id, f"用户 {user.username} 创建了任务 {dbtask.name}"))
            dbrecord.commit()
        return {"code": 20000, "data": id}
    
def edit_task(model: EditTaskModel, user: User):
    verify_car_number(model.car_numbers)
    with TaskTable() as db:
        dbtask = findDbTaskRecord(model.id)
        if not dbtask:
            raise ParkAdminException(ParkAdminErrorCode.TaskNotFound)
        if dbtask.user_id != user.id and not user.isadmin():
            raise ParkAdminException(ParkAdminErrorCode.NoPermission)
        dbtask.name = model.name
        dbtask.platform_id = model.platform_id
        dbtask.proxy = model.proxy
        dbtask.threads = model.threads
        dbtask.car_numbers = model.car_numbers
        db.update(dbtask)
        db.commit()
        with TaskRecordTable() as dbrecord:
            dbrecord.insert(buildDbTaskRecord(user.id, dbtask.id, f"用户 {user.username} 修改了任务 {dbtask.name}"))
            dbrecord.commit()
        return {"code": 20000}
    
def delete_task(model: OperationTaskModel, user: User):
    with TaskTable() as db:
        dbtask = findDbTaskRecord(model.id)
        if not dbtask:
            raise ParkAdminException(ParkAdminErrorCode.TaskNotFound)
        if dbtask.user_id != user.id and not user.isadmin():
            raise ParkAdminException(ParkAdminErrorCode.NoPermission)
        db.delete(model.id)
        db.commit()
        with TaskRecordTable() as dbrecord:
            dbrecord.insert(buildDbTaskRecord(user.id, model.id, f"用户 {user.username} 删除了任务 {model.name}"))
            dbrecord.commit()
        return {"code": 20000}

def request_task(id, options):
    rsp = requests.post(url=f'{spider_host}/api/parkspider/task', json={"task_id": id, "options": options})
    rspJson = rsp.json()
    if rspJson['code'] != 0:
        raise ParkAdminException(ParkAdminErrorCode.SpiderError, rspJson['message'])
    return {"code": 20000}

def start_task(model: OperationTaskModel, user: User):
    with TaskTable() as db:
        dbtask = findDbTaskRecord(model.id)
        if not dbtask:
            raise ParkAdminException(ParkAdminErrorCode.TaskNotFound)
        if dbtask.user_id != user.id and not user.isadmin():
            raise ParkAdminException(ParkAdminErrorCode.NoPermission)
        if dbtask.status == TaskStatus.Running:
            raise ParkAdminException(ParkAdminErrorCode.TaskRunning)
        # dbtask.status = TaskStatus.Running
        # db.update(dbtask)
        # db.commit()
        with TaskRecordTable() as dbrecord:
            dbrecord.insert(buildDbTaskRecord(user.id, model.id, f"用户 {user.username} 启动了任务 {model.name}"))
            dbrecord.commit()
        return request_task(model.id, 1)

def stop_task(model: OperationTaskModel, user: User):
    with TaskTable() as db:
        dbtask = findDbTaskRecord(model.id)
        if not dbtask:
            raise ParkAdminException(ParkAdminErrorCode.TaskNotFound)
        if dbtask.user_id != user.id and not user.isadmin():
            raise ParkAdminException(ParkAdminErrorCode.NoPermission)
        # dbtask.status = TaskStatus.Stop
        # db.update(dbtask)
        # db.commit()
        with TaskRecordTable() as dbrecord:
            dbrecord.insert(buildDbTaskRecord(user.id, model.id, f"用户 {user.username} 停止了任务 {model.name}"))
            dbrecord.commit()
        return request_task(model.id, 2)

def polling_taskrecord(total: int, query: TaskQuery, user: User):
    with TaskRecordTable() as db:
        if not user.isadmin(): query.user_id = user.id
        new_total = db.query(query, True)
        return {"code": 20000, "data": new_total != total}
    
def polling_parkrecord(total: int, query: ParkQuery, user: User):
    with ParkRecordTable() as db:
        if not user.isadmin(): query.user_id = user.id
        new_total = db.query(query, True)
        return {"code": 20000, "data": new_total != total}